package com.bcxj.apipassenger.service;

import com.bcxj.apipassenger.remote.ServiceUserClient;
import com.bcxj.apipassenger.remote.ServiceVerificationCodeClient;
import com.bcxj.internalcommon.constant.*;
import com.bcxj.internalcommon.dto.VerificationCodeDTO;
import com.bcxj.internalcommon.response.ResponseResult;
import com.bcxj.internalcommon.util.JwtUtils;
import com.bcxj.internalcommon.util.RedisPrefixUtils;
import com.bcxj.internalcommon.vo.TokenVO;
import com.bcxj.internalcommon.vo.VerificationCodeVO;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * ClassName: VerificationCodeService
 * Package: com.bcxj.apipassenger.service
 * Description:
 *
 * @Author BCXJ
 * @Create 2025/2/10 22:34
 * @Version 1.0
 * @Since 1.0
 */
@Slf4j
@Service
public class VerificationCodeService {

    @Autowired
    private ServiceVerificationCodeClient serviceVerificationCodeClient;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ServiceUserClient serviceUserClient;

    /**
     * service 对应的用户登录时获取手机验证码
     * @param verificationCodeDTO
     * @return
     */
    public ResponseResult<VerificationCodeVO> getVerificationCode(VerificationCodeDTO verificationCodeDTO) {
        // 0 获取手机号
        String userPhone = verificationCodeDTO.getUserPhone();
        // 1 远程调用验证码
        ResponseResult<VerificationCodeVO> result = serviceVerificationCodeClient.numberCode(CommonConstant.PHONE_LENGTH);

        // 2 获取验证码
        String code = result.getData().getCode();

        log.info("手机号为：" + userPhone + "验证码为：" + code);

        // 2.1 验证码存入redis, 时间为1分钟
        redisTemplate.opsForValue().set(RedisPrefixKey.USER_CODE + userPhone, code, 1, TimeUnit.MINUTES);

        // 3. 第三方api(省略)

        return ResponseResult.success();
    }


    /**
     * 验证验证码 + 创建新用户 + 颁发token
     * @param verificationCodeDTO
     * @return
     */
    public ResponseResult check(VerificationCodeDTO verificationCodeDTO) {
        // 1 校验用户输入的验证码与手机号
        String key = RedisPrefixKey.USER_CODE + verificationCodeDTO.getUserPhone();
        String code = redisTemplate.opsForValue().get(key);
        if(StringUtils.isBlank(verificationCodeDTO.getVerificationCode()) || StringUtils.isBlank(code)) {
            return ResponseResult.fail(CommonStatusEnum.USER_CODE_NULL);
        }else if(!code.equals(verificationCodeDTO.getVerificationCode().trim())) {
            // 验证码不匹配
            return ResponseResult.fail(CommonStatusEnum.USER_CODE_ERROR);
        }

        log.info("验证码效验通过");

        // 2 创建新用户（远程调用)
        ResponseResult responseResult = serviceUserClient.loginOrRegister(verificationCodeDTO);
        log.info("用户创建的远程调用结果：" + responseResult.getData());

        // 3 颁发token
        // 3 生成并返回accesstoken
        String accessToken = JwtUtils.generatorToken(verificationCodeDTO.getUserPhone(), IdentityConstant.USER_IDENTITY, TokenConstant.ACCESS_TOKEN);
        String refreshToken = JwtUtils.generatorToken(verificationCodeDTO.getUserPhone(), IdentityConstant.USER_IDENTITY, TokenConstant.REFRESH_TOKEN);
        // 3. token存入Redis中的数据
        String accessTokenKey = RedisPrefixUtils.generatorTokenKey(verificationCodeDTO.getUserPhone(), IdentityConstant.USER_IDENTITY, TokenConstant.ACCESS_TOKEN);
        String refreshTokenKey = RedisPrefixUtils.generatorTokenKey(verificationCodeDTO.getUserPhone(), IdentityConstant.USER_IDENTITY, TokenConstant.REFRESH_TOKEN);
        // 3.1. 将token存入redis
        redisTemplate.opsForValue().set(accessTokenKey, accessToken, 30, TimeUnit.MINUTES);
        redisTemplate.opsForValue().set(refreshTokenKey, refreshToken, 1, TimeUnit.DAYS);

        // 3.2 返回token
        TokenVO tokenResponse = new TokenVO();
        tokenResponse.setAccessToken(accessToken);
        tokenResponse.setRefreshToken(refreshToken);
        return ResponseResult.success(tokenResponse);
    }

}
